package com.soa.zuul.filter;

import java.io.PrintWriter;
import java.io.StringWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.netflix.zuul.util.ZuulRuntimeException;
import org.springframework.util.ReflectionUtils;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import com.soa.zuul.service.FeignLogService;
import com.soa.zuul.util.CodeMsg;
import com.soa.zuul.util.Json;

/**
 * 异常返回
 * 
 * @author zheng
 *
 */
public class ErrorFilter extends ZuulFilter {
	public final static Logger logger = LoggerFactory.getLogger(ErrorFilter.class);
	FeignLogService feignLogService;
	public ErrorFilter(FeignLogService feignLogService) {
		this.feignLogService=feignLogService;
	}

	@Override
	public String filterType() {
		// 异常过滤器
		return "error";
	}

	@Override
	public int filterOrder() {
		// 优先级，数字越大，优先级越低
		return 0;
	}

	@Override
	public boolean shouldFilter() {
		 RequestContext ctx = RequestContext.getCurrentContext();
		 if(ctx.get("isSuccess")==null) return false;
		 return (boolean) ctx.get("isSuccess");//
	}

	@Override
	public Object run() {
		try {
			RequestContext context = RequestContext.getCurrentContext();
			HttpServletRequest request = context.getRequest();
			if (request == null)return null;
			HttpServletResponse response = context.getResponse();
			response.setContentType("application/json; charset=utf8");
			Throwable throwable = context.getThrowable();
			Throwable thisThrowable = getOriginException(throwable);
			CodeMsg codeMsg = CodeMsg.GATEWAY_ERROR;
			codeMsg.setResponse(throwable);
			logger.error("进入系统异常拦截", throwable);
			// 链接超时
			if (thisThrowable instanceof java.net.SocketTimeoutException) {
				codeMsg = CodeMsg.TIME_OUT;
			}
			// 限流启用
			if (thisThrowable instanceof com.netflix.zuul.exception.ZuulException) {
				ZuulException exception = this.findZuulException(context.getThrowable());
				if (exception.nStatusCode == 429) {
					codeMsg = CodeMsg.SERVICE_BUSSNESS;
				}
				if (exception.nStatusCode == 404) {
					codeMsg = CodeMsg.SERVICE_404;
				}
			}
			if (thisThrowable instanceof java.net.ConnectException) {
				codeMsg = CodeMsg.SERVICE_CONNECTEXCEPTION;
			}
			if (thisThrowable instanceof com.netflix.client.ClientException) {
				codeMsg = CodeMsg.SERVICE_NETFLIX_ERROR;
			}
			PrintWriter writer = null;
			writer = response.getWriter();
			codeMsg.setResponse(thisThrowable);
			writer.print(Json.GSON.toJson(codeMsg));
			writer.close();
		} catch (Exception var5) {
			var5.printStackTrace();
			ReflectionUtils.rethrowRuntimeException(var5);
		}
		return null;
	}

	ZuulException findZuulException(Throwable throwable) {
		if (ZuulRuntimeException.class.isInstance(throwable.getCause())) {
			return (ZuulException) throwable.getCause().getCause();
		} else if (ZuulException.class.isInstance(throwable.getCause())) {
			return (ZuulException) throwable.getCause();
		} else {
			return ZuulException.class.isInstance(throwable) ? (ZuulException) throwable
					: new ZuulException(throwable, 500, (String) null);
		}
	}

	Throwable getOriginException(Throwable e) {
		e = e.getCause();
		while (e.getCause() != null) {
			e = e.getCause();
		}
		return e;
	}

	private static String toString_02(Throwable e) {
		StringWriter sw = new StringWriter();
		PrintWriter pw = new PrintWriter(sw, true);
		e.printStackTrace(pw);
		pw.flush();
		sw.flush();
		return sw.toString();
	}
}
